package edu.mapi.aamas.renderer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.locks.ReentrantLock;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Group;
import javax.media.j3d.LineArray;
import javax.media.j3d.Locale;
import javax.media.j3d.Material;
import javax.media.j3d.RenderingAttributes;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TransparencyAttributes;
import javax.media.j3d.View;
import javax.media.j3d.VirtualUniverse;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JToolBar;
import javax.swing.border.BevelBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.mnstarfire.loaders3d.Inspector3DS;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.scenegraph.io.SceneGraphFileReader;
import com.sun.j3d.utils.scenegraph.io.SceneGraphStreamReader;
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.ContentType;

import edu.mapi.aamas.common.VehicleState;


//import com.sun.j3d.utils.behaviors.picking.PickObject;

/***
 * 
 * @author RJPG
 * Generic Class to display 3D graphics with multiple views and functionalities  
 *  
 */
public class Renderer3D extends JPanel implements ActionListener , MouseListener, MouseMotionListener, KeyListener, MouseWheelListener
{	
	private static final long serialVersionUID = 1L;
	public static final int TRANSLATION = 1, ZOOM = 2, ROTATION = 3, RULER = 4, NONE = -1;
	
		//roll-phi-X
		//pitch-theta-Y
		//yaw-psi-Z
/*-------------------- desta classe---------------------------*/
   protected int NVIEWS=4;   // N vistas: 4 neste momento
	
   /*------------------vari�veis de JavaSwing--------------------*/
   private JPanel[] views; // panel[] vistas
   private JPanel viewspanel= new JPanel();     // para juntar todas
   JToolBar toolbar = new JToolBar("Controls"); // vai sair 
	
   /*------------------vari�veis de Java3D-----------------------*/
   private VirtualUniverse universe;  	   //Universo
   private Locale locale; 				   //node Locale
   private BoundingSphere bounds;		   //limites do universo
   
   private BranchGroup contentBranch;  	   //BranchGroup para os objectos
   private TransformGroup contentsTransGr; //n� de transforma��o de toda a sena	
   private TransformGroup contentsTransGr2;
   
   private BranchGroup viewBranch; 		   //BranchGroup para a parte das vistas
   private TransformGroup viewTransGr;     //n� de transforma��o de toda a sena	
      
   /*------------------vari�veis da aplica��o--------------------*/
   public Hashtable objects = new Hashtable();    //Hash para o mapa
  
   public Camera3D[] cams;

   
   /*------------------------executar codigo atomicamente -------------*/
   ReentrantLock lock= new ReentrantLock();
   
   /*----------------vars auxs de controle de menus--------------*/
   public short panel_op=0;
   private short lines=2,coluns=2; 
   private short panel_max=-1;

   private short viewing=1;

   private boolean grid=false;


   private short rule=0;
   //Dimension d;
   
   //----------------------grid 
   public boolean gNE=true;
   public boolean gUE=false;
   public boolean gUN=false;
   
   public float gdimension=10.0f;
   public float gspacing=1.0f;
   public boolean gtext=false;
   
   public Color gcolor = new Color(0.8f,0.8f,0.8f);
   public Point3d gcenter=new Point3d(0.0f,0.0f,0.0f);
   
   //----------------------mouse...
   private boolean mouse1=false;//direito 
   //private boolean mouse2=false;//meio
   private boolean mouse3=false;//esquerdo
   private int mousex,mousey;
   private Cursor rotateCursor, translateCursor, zoomCursor;
   //----------------------modelos
   BranchGroup landscape;
   Obj3D seaobj; //mar
   Obj3D lochomeobj; // origem 
   Obj3D gridobj;  // grelha
   
   /*------------------------M�todos-----------------------------*/
   
   
   public Hashtable<String , Obj3D> Vehicles=new Hashtable<String, Obj3D>();
   public Hashtable<String , Obj3D> destination=new Hashtable<String, Obj3D>();
   
 /**
 * 	Default constructor with four views in 2*2 Layout
 *  
 */
public Renderer3D()
   {
	//Runtime r = Runtime.getRuntime();
		
   		Camera3D cs[]=new Camera3D[4];
   		try {
   			cs[0]=new Camera3D(Camera3D.TOP);  //top
   			cs[1]=new Camera3D(Camera3D.RIGHT);  //left
   			cs[2]=new Camera3D(Camera3D.BACK);  //front
   			cs[3]=new Camera3D(Camera3D.USER);  //user*/
   		}
   		catch(Exception e)
		{
   			System.out.println("Erro Render-3D"+"erro iniciando Vistas");
   			return;
		}
   		/*try {//nada
   			System.out.println("espera...");
   			Thread.sleep(5000);
   			System.out.println("esperou");
   		}
   		catch (Exception e){
   			System.out.println("excepcao");
   		}*/
   		
   		cams=cs;
   		NVIEWS=4;
   		lines=2;coluns=2;
   		createLayout(lines,coluns);
   		init3D();
   		setCoordinateSystem();
   		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
   		setViewMode(Renderer3D.TRANSLATION);
   	// r.gc(); 
   }
   
   /**
 * @param cs  array of Camera3D
 * @param rows of Layout
 * @param cols of Layout
 */
public Renderer3D(Camera3D cs[],short rows,short cols)
   {
	
	setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
	
	//Runtime r = Runtime.getRuntime();
   		NVIEWS=cs.length;   	
   		cams=cs;
   		lines=rows;
   		coluns=cols;
   		createLayout(rows,cols);
   		init3D();
   	 //r.gc(); 
   		//setCoordinateSystem(); 
   		//System.out.println(NVIEWS);
   		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
   		setViewMode(Renderer3D.TRANSLATION);
   		
   }
   



private void loadCursors() {

	rotateCursor = Toolkit.getDefaultToolkit().createCustomCursor( new ImageIcon(this.getClass().getClassLoader().getResource("cursors/rotate_cursor.png")).getImage(), new java.awt.Point(15,15), "Rotate");
	zoomCursor = Toolkit.getDefaultToolkit().createCustomCursor( new ImageIcon(this.getClass().getClassLoader().getResource("cursors/zoom_cursor.png")).getImage(), new java.awt.Point(15,15), "Zoom");
	translateCursor = Toolkit.getDefaultToolkit().createCustomCursor( new ImageIcon(this.getClass().getClassLoader().getResource("cursors/translate_cursor.png")).getImage(), new java.awt.Point(15,15), "Translate");
}


   /**
 * @param c Camera3D to add (attach) on scene  
 */
void addCamera3D(Camera3D c)
   {
   		viewTransGr.addChild(c.getCamera3D());
   }
   
   
 
   private void createLayout(int rows,int coluns)
   {
   		viewspanel.setLayout(new GridLayout(rows,coluns));
   		views=new JPanel[NVIEWS];
   		for(int i=0;i<NVIEWS;i++)
   		{
   			views[i]=new JPanel();
   			views[i].setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
   			viewspanel.add(views[i]);
   			//views[i].setBackground(Color.RED);
   			views[i].setVisible(true);
   			//System.out.println("pus"+i);  //OK	
   		}
   		
   		this.setLayout(new BorderLayout());
		this.add(viewspanel, BorderLayout.CENTER);
		

   }
   
   /**
 * init 3d environment
 */
   
   Hashtable<String, TransformGroup> models=new Hashtable<String, TransformGroup>();
   
private void init3D()
   {
	
   
		
   		// Limites (generico)
   		bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
  		
   		setUniverse();// Raiz da arvore(inicio do Grafo)
   		setContent(); // conteudo da "sena"
   		setViewing(); //posicionar cameras
   		
   		TransformGroup APVModel=new TransformGroup();
		TransformGroup LusitaniaModel=new TransformGroup();
		TransformGroup BrutusModel=new TransformGroup();
		TransformGroup SilverFoxModel=new TransformGroup();
		
   		File file=null;
		System.out.println("Loading apv");
		//file=new File(getClass().getClassLoader().getResource("models/apv.3ds").getFile());
		Inspector3DS loader  = new Inspector3DS(getClass().getClassLoader().getResource("models/apv.3ds"));
		loader.parseIt(); // process the file
		APVModel  = loader.getModel(); // get the resulting 3D
		   
		System.out.println("Loading brutus");
		//file=new File(getClass().getClassLoader().getResource("models/brutus.3ds").getFile());
		loader  = new Inspector3DS(getClass().getClassLoader().getResource("models/brutus.3ds"));
		loader.parseIt(); // process the file
		BrutusModel  = loader.getModel(); // get the resulting 3D
		
		System.out.println("Loading lusitania");
		//file=new File(getClass().getClassLoader().getResource("models/lusitania.3ds").getFile());
		loader  = new Inspector3DS(getClass().getClassLoader().getResource("models/lusitania.3ds"));
		loader.parseIt(); // process the file
		LusitaniaModel  = loader.getModel(); // get the resulting 3D

		System.out.println("Loading silver-fox");
		//file=new File(getClass().getClassLoader().getResource("models/silver-fox.3ds").getFile());		
		loader  = new Inspector3DS(getClass().getClassLoader().getResource("models/silver-fox.3ds"));
		loader.parseIt(); // process the file
		SilverFoxModel  = loader.getModel(); // get the resulting 3D
		
		Transform3D t=new Transform3D();
		Transform3D trot=new Transform3D();
		t.setScale(5);
		trot.rotX(Math.PI);
		
		t.mul(trot);
		APVModel.setTransform(t);
		BrutusModel.setTransform(t);
		LusitaniaModel.setTransform(t);
		SilverFoxModel.setTransform(t);
		
		
		models.put("apv", APVModel);
		models.put("brutus", BrutusModel);
		models.put("lusitania", LusitaniaModel);
		models.put("silver-fox", SilverFoxModel);
		//TransformGroup theModel1;
		//theModel1=(TransformGroup) models.get("apv").cloneTree();
		//Obj3D obj=new Obj3D();
		//obj.setModel3D(null);
		//addObj3D(obj);
   }
   
public void reset()
{
	//locale.removeBranchGraph(contentBranch);
	//contentsTransGr.removeAllChildren();
	//setContent();
}

   /**
 * 	init the contetns of the scene (lights bacground capabilities)
 */
private void setContent(){
   		contentsTransGr = new TransformGroup();
   		contentsTransGr.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   		contentsTransGr.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   		contentsTransGr.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
   		contentsTransGr.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
   		contentsTransGr.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
   		
   		contentBranch = new BranchGroup();
   		contentBranch.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
   		//   	 novo Backgroung  2, 113, 171
		//              0.007843137254901961 
   		//Color3f bgColor   = new Color3f(0.1f, 0.1f, 0.4f);
		//Background bg = new Background(bgColor);
		//bg.setApplicationBounds(bounds);
		//contentBranch.addChild(bg);
		
		Background bg = new Background();
		bg.setApplicationBounds(bounds);
		BranchGroup backGeoBranch = new BranchGroup();
		Sphere sphereObj = new Sphere(1.0f, Sphere.GENERATE_NORMALS
				| Sphere.GENERATE_NORMALS_INWARD
				| Sphere.GENERATE_TEXTURE_COORDS, 90);
		Appearance backgroundApp = sphereObj.getAppearance();
		TransformGroup rotx = new TransformGroup();
		Transform3D rot = new Transform3D();
		rot.rotX(Math.PI / 2);
		rotx.setTransform(rot);
		rotx.addChild(sphereObj);
		backGeoBranch.addChild(rotx);
		bg.setGeometry(backGeoBranch);
		Image texture = new ImageIcon(this.getClass().getClassLoader().getResource("images/backsky.png")).getImage();
		//GuiUtils.getImage("images/backsky.png");
		TextureLoader tex = new TextureLoader(texture, new String("RGB"),
				this);
		if (tex != null)
			backgroundApp.setTexture(tex.getTexture());

		

		contentBranch.addChild(bg);

			
		BranchGroup ota=null;
		File file=new File(System.getProperty(".","tmp"));
		Util3D.copyStreamToFile(getClass().getClassLoader().getResourceAsStream("models/ota-map.j3d"),file);
		//file=new File(getClass().getClassLoader().getResource("models/ota-map.j3d").getFile());
		try {
			//SceneGraphFileReader file=new SceneGraphFileReader();
			//file.
			//InputStream input=new InputStream();
			
			SceneGraphFileReader filer=new SceneGraphFileReader(file);
			ota=filer.readAllBranchGraphs()[0];
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(bg==null)
		{
			System.err.println("Error loading vehicle model\n" + this);
		}
		TransformGroup scene = new TransformGroup();
		
		Enumeration<Group> enume = ota.getAllChildren();
		while (enume.hasMoreElements()) {
			Group next = enume.nextElement();
			ota.removeChild(next);
			scene.addChild(next);
		}
		
		
		Transform3D rotate = new Transform3D();
		rotate.rotX(Math.PI);
		scene.setTransform(rotate);
		
		contentBranch.addChild(scene);
		
		setLighting();

		//------------------------------------GRID
		makeGrid();
		
		
		//------------------------------------------------------------
		
		    /*ColorCube cube2 = new ColorCube(0.25);
		    
		    contentsTransGr.addChild(cube2);
		    contentsTransGr.setTransform(t1);*/
	
		//System.out.println("novo obj");	
		//contentsTransGr: � aqui que ligam todos os objectos
		
		
		/*//teste de linhas
		Point3d myCoords[]= new Point3d[2]; 
    	myCoords[0]=new Point3d(0.0,0.0,0.0);
    	myCoords[1]=new Point3d(10.0,10.0,10.0);
    	LineArray myLines = new LineArray(
    			myCoords.length,
				LineArray.COORDINATES  | LineArray.COLOR_3 );
    	myLines.setCoordinates( 0, myCoords );
        Shape3D shape3D = new Shape3D(myLines);
    	 //shape3D.setCapability(Shape3D.ENABLE_APPEARANCE_MODIFY);
    	contentsTransGr.addChild(shape3D);
		*/
		
		contentBranch.addChild(contentsTransGr);
		//contentBranch.compile();			
		locale.addBranchGraph(contentBranch);
   	
   }
private void deactivateMap()
{
	
}

public void addObj3D(Obj3D obj)
{

	obj.setParent3D(contentsTransGr);	
}

public void removeObj3D(Obj3D obj)
{
	contentsTransGr.removeChild(obj.getFullObj3D());
}


private void makeGrid()
{
	TransformGroup theModel  = new TransformGroup();
	theModel.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	theModel.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
	theModel.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
	theModel.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
	theModel.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
	
	
	RenderingAttributes renderingAttributes = new RenderingAttributes(true, // boolean
																			// depthBufferEnable,
				true, // boolean depthBufferWriteEnable,
				1.0f, // float alphaTestValue,
				RenderingAttributes.ALWAYS, // int alphaTestFunction,
				true, // boolean visible,
				true, // boolean ignoreVertexColors,
				false, // boolean rasterOpEnable,
				RenderingAttributes.ROP_COPY // int rasterOp
		);
		Color3f c = new Color3f(gcolor);
		ColoringAttributes coloringAttributes = new ColoringAttributes(c,
				ColoringAttributes.SHADE_GOURAUD);
		Appearance appearance = new Appearance();
		appearance.setRenderingAttributes(renderingAttributes);
		appearance.setColoringAttributes(coloringAttributes);

		if (gNE)
		{
		int i=(int)(gdimension/gspacing);
		int x=0;
		float step=0.f;
		int index=0;
		Point3d listp[] = new Point3d[(i+1)*2];
		while(x<i+1)
		{
			listp[index] = new Point3d(gdimension/2, (-gdimension/2)+step, 0.0);
			index++;
			listp[index] = new Point3d(-gdimension/2, (-gdimension/2)+step, 0.0);
			index++;
			x++;
			step+=gspacing;
		}
		
		/*listp[2] = new Point3d(0.0, 4, 0.0);
		listp[3] = new Point3d(0.0, -4, 0.0);
		listp[4] = new Point3d(0.0, 0.0, 4);
		listp[5] = new Point3d(0.0, 0.0, -4);*/

		LineArray myLines = new LineArray(listp.length, LineArray.COORDINATES);
		myLines.setCoordinates(0, listp);
		Shape3D shape3D = new Shape3D(myLines, appearance);

		
		i=(int)(gdimension/gspacing);
		x=0;
		step=0.f;
		index=0;
		Point3d listp2[] = new Point3d[(i+1)*2];
		while(x<i+1)
		{
			listp2[index] = new Point3d((-gdimension/2)+step,+gdimension/2, 0.0);
			index++;
			listp2[index] = new Point3d((-gdimension/2)+step,-gdimension/2, 0.0);
			index++;
			x++;
			step+=gspacing;
		}
		

		
		
		/*listp[2] = new Point3d(0.0, 4, 0.0);
		listp[3] = new Point3d(0.0, -4, 0.0);
		listp[4] = new Point3d(0.0, 0.0, 4);
		listp[5] = new Point3d(0.0, 0.0, -4);*/

		LineArray myLines2 = new LineArray(listp2.length, LineArray.COORDINATES);
		myLines2.setCoordinates(0, listp2);
		Shape3D shape3D2 = new Shape3D(myLines2, appearance);
		theModel.addChild(shape3D);
		theModel.addChild(shape3D2);
	}
		
		if (gUE)
		{
		int i=(int)(gdimension/gspacing);
		int x=0;
		float step=0.f;
		int index=0;
		Point3d listp[] = new Point3d[(i+1)*2];
		while(x<i+1)
		{
			listp[index] = new Point3d(0.0f,gdimension/2, (-gdimension/2)+step);
			index++;
			listp[index] = new Point3d(0.0f,-gdimension/2, (-gdimension/2)+step);
			index++;
			x++;
			step+=gspacing;
		}
		
		/*listp[2] = new Point3d(0.0, 4, 0.0);
		listp[3] = new Point3d(0.0, -4, 0.0);
		listp[4] = new Point3d(0.0, 0.0, 4);
		listp[5] = new Point3d(0.0, 0.0, -4);*/

		LineArray myLines = new LineArray(listp.length, LineArray.COORDINATES);
		myLines.setCoordinates(0, listp);
		Shape3D shape3D = new Shape3D(myLines, appearance);

		
		i=(int)(gdimension/gspacing);
		x=0;
		step=0.f;
		index=0;
		Point3d listp2[] = new Point3d[(i+1)*2];
		while(x<i+1)
		{
			listp2[index] = new Point3d(0.0f,(-gdimension/2)+step,+gdimension/2);
			index++;
			listp2[index] = new Point3d(0.0f,(-gdimension/2)+step,-gdimension/2);
			index++;
			x++;
			step+=gspacing;
		}
		

		
		
		/*listp[2] = new Point3d(0.0, 4, 0.0);
		listp[3] = new Point3d(0.0, -4, 0.0);
		listp[4] = new Point3d(0.0, 0.0, 4);
		listp[5] = new Point3d(0.0, 0.0, -4);*/

		LineArray myLines2 = new LineArray(listp2.length, LineArray.COORDINATES);
		myLines2.setCoordinates(0, listp2);
		Shape3D shape3D2 = new Shape3D(myLines2, appearance);
		theModel.addChild(shape3D);
		theModel.addChild(shape3D2);
	}
		
		
	if (gUN)
		{
		int i=(int)(gdimension/gspacing);
		int x=0;
		float step=0.f;
		int index=0;
		Point3d listp[] = new Point3d[(i+1)*2];
		while(x<i+1)
		{
			listp[index] = new Point3d(gdimension/2,0.0f, (-gdimension/2)+step);
			index++;
			listp[index] = new Point3d(-gdimension/2,0.0f, (-gdimension/2)+step);
			index++;
			x++;
			step+=gspacing;
		}
		
		/*listp[2] = new Point3d(0.0, 4, 0.0);
		listp[3] = new Point3d(0.0, -4, 0.0);
		listp[4] = new Point3d(0.0, 0.0, 4);
		listp[5] = new Point3d(0.0, 0.0, -4);*/

		LineArray myLines = new LineArray(listp.length, LineArray.COORDINATES);
		myLines.setCoordinates(0, listp);
		Shape3D shape3D = new Shape3D(myLines, appearance);

		
		i=(int)(gdimension/gspacing);
		x=0;
		step=0.f;
		index=0;
		Point3d listp2[] = new Point3d[(i+1)*2];
		while(x<i+1)
		{
			listp2[index] = new Point3d((-gdimension/2)+step,0.0f,+gdimension/2);
			index++;
			listp2[index] = new Point3d((-gdimension/2)+step,0.0f,-gdimension/2);
			index++;
			x++;
			step+=gspacing;
		}
		

		
		
		/*listp[2] = new Point3d(0.0, 4, 0.0);
		listp[3] = new Point3d(0.0, -4, 0.0);
		listp[4] = new Point3d(0.0, 0.0, 4);
		listp[5] = new Point3d(0.0, 0.0, -4);*/

		LineArray myLines2 = new LineArray(listp2.length, LineArray.COORDINATES);
		myLines2.setCoordinates(0, listp2);
		Shape3D shape3D2 = new Shape3D(myLines2, appearance);
		theModel.addChild(shape3D);
		theModel.addChild(shape3D2);
	}
		
		
		
		
		
	
	
	
	
	gridobj=new Obj3D(theModel);
}

public void menuOKgrid()
{
	
	
	if(grid){
		contentsTransGr.removeChild(gridobj.getFullObj3D());
		this.makeGrid();
		gridobj.setPos(gcenter);
		gridobj.setParent3D(contentsTransGr);
		
	}
	else
	{
		this.makeGrid();
		gridobj.setPos(gcenter);
	}
	
}

private void setLighting()
	{
		AmbientLight ambientLight =  new AmbientLight();
		ambientLight.setEnable(true);
		ambientLight.setColor(new Color3f(0.7f, 0.7f, 0.7f) );
		ambientLight.setCapability(AmbientLight.ALLOW_STATE_READ);
		ambientLight.setCapability(AmbientLight.ALLOW_STATE_WRITE);
		ambientLight.setInfluencingBounds(bounds);
		contentsTransGr.addChild(ambientLight);
		
		DirectionalLight dirLight =  new DirectionalLight();
		dirLight.setEnable(true);
		dirLight.setColor( new Color3f( 0.6f, 0.6f, 0.6f ));
		dirLight.setDirection( new Vector3f( 1f, 1f, 1f ));
		dirLight.setCapability( AmbientLight.ALLOW_STATE_WRITE );
		dirLight.setInfluencingBounds(bounds);
		contentsTransGr.addChild(dirLight);
		
		DirectionalLight dirLight2 =  new DirectionalLight();
		dirLight2.setEnable(true);
		dirLight2.setColor( new Color3f( 0.7f, 0.7f, 0.7f ) );
		dirLight2.setDirection( new Vector3f( -1f, -1f, -1f ) );
		dirLight2.setCapability( AmbientLight.ALLOW_STATE_WRITE );
		dirLight2.setInfluencingBounds(bounds);
		contentsTransGr.addChild(dirLight2);
	}
   
   /**
 * 	init the viewBranch
 */
private void setViewing()
   {
   		viewBranch = new BranchGroup();
   		viewTransGr=new TransformGroup();
   		viewTransGr.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
   		viewTransGr.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
   		viewTransGr.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
   		viewTransGr.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
   		viewTransGr.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
   		
   		for(int i=0;i<NVIEWS;i++)
   		{
   			views[i].setLayout(new BorderLayout());
   			views[i].add(cams[i].canvas,BorderLayout.CENTER);
   			addCamera3D(cams[i]);
   			cams[i].associatedrender=this;
   			cams[i].canvas.startRenderer();
   			cams[i].canvas.addMouseListener(this);
   			cams[i].canvas.addMouseMotionListener(this);
   			cams[i].canvas.addKeyListener(this);
   			cams[i].canvas.addMouseWheelListener(this);
   			//AUX();
   			
   		}
   		viewBranch.addChild(viewTransGr);
   		locale.addBranchGraph(viewBranch);
   		
   		
   }
   
  public void unfreeze()
  {
	for(int i=0;i<NVIEWS;i++)
		{
			cams[i].canvas.addMouseListener(this);
			cams[i].canvas.addMouseMotionListener(this);
			cams[i].canvas.addKeyListener(this);
			cams[i].canvas.addMouseWheelListener(this);
			//AUX();
			
		}
  }
  public void freeze()
  {
	for(int i=0;i<NVIEWS;i++)
		{
			cams[i].canvas.removeMouseListener(this);
			cams[i].canvas.removeMouseMotionListener(this);
			cams[i].canvas.removeKeyListener(this);
			cams[i].canvas.removeMouseWheelListener(this);
			//AUX();
			
		}
  }

  public void noborder()
  {
	for(int i=0;i<NVIEWS;i++)
		{
			views[i].setBorder(BorderFactory.createEmptyBorder());	
		}	
  }
  
  public void border()
  {
  	for(int i=0;i<NVIEWS;i++)
	{
		views[i].setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
	
	}
  }
  
   private void setUniverse()
   {
   	// Creating the VirtualUniverse and the Locale nodes
		universe = new VirtualUniverse();
		locale = new Locale(universe);
	
	}
   
  /**
   *  inverse z axis(Cameras inverse as well...)
   */
   public void setCoordinateSystem() //NED ou NWU...
   {
   		Transform3D t=new Transform3D();
   		t.rotX(Math.PI);//s� isto para j� 
   		t.rotY(0.0);
   		t.rotZ(0.0);	
   		contentsTransGr.setTransform(t);   //ajustes nos objs
   		viewTransGr.setTransform(t);       //ajustes nas cams
   }
   

   
   /*--------------------------main para testar------------------*/
   public static void main(String args[]) 
   {	
   	

   		
   		Camera3D cs[]=new Camera3D[1];  //escolher uma cam de lado 
   		cs[0]=new Camera3D(Camera3D.RIGHT);  //top
   		cs[0].setScale(1.5f);
   		cs[0].setPivot(new Vector3d(-0.08,0,0));
   		
   		/*cs[1]=new Camera3D(Camera3D.RIGHT);  //left
   		cs[2]=new Camera3D(Camera3D.BACK);  //front
   		cs[3]=new Camera3D(Camera3D.USER);  //user*/
   		
   		Renderer3D r=new Renderer3D(cs,(short)1,(short)1);  // 1 por 1
		
   		JFrame a = new JFrame("Render");
		a.setSize(500,400);
		a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		a.getContentPane().setLayout(new BorderLayout());
		a.getContentPane().add(r,BorderLayout.CENTER);
		a.setVisible(true);
		
//		r.setVisible(true);
		int i=0;

   }

 

/* (non-Javadoc)
 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
 */
public void actionPerformed(ActionEvent e) {
	if ("maximize".equals(e.getActionCommand())) {
		for(int i=0;i<NVIEWS;i++)
		{
			viewspanel.remove(views[i]);
			//cams[i].canvas.stopRenderer();
		}
		for(int i=0;i<NVIEWS;i++)    // para for�ar a ltera��o do tamanho de todas as canvas 
		{                            // para o desenho2d n�o se passar...
		if (i!=panel_op)             // panal_op j� vai alterar o seu tam � frente
		{
		viewspanel.setLayout(new BorderLayout());
		cams[i].canvas.startRenderer();
		viewspanel.add(views[i],BorderLayout.CENTER);
		viewspanel.doLayout();
		views[i].doLayout();
		panel_max=panel_op;
		}
		}
		for(int i=0;i<NVIEWS;i++)
		{
			viewspanel.remove(views[i]);
			//cams[i].canvas.stopRenderer();
		}
		viewspanel.setLayout(new BorderLayout());
		cams[panel_op].canvas.startRenderer();
		viewspanel.add(views[panel_op],BorderLayout.CENTER);
		viewspanel.doLayout();
		views[panel_op].doLayout();
		panel_max=panel_op;
		
		return;
	}
	if ("restore".equals(e.getActionCommand())) {
		//boolean auxc=cams[panel_max].canvas.caminfo; //info cam *
		viewspanel.remove(views[panel_op]);
		
		//cams[panel_op].canvas.stopRenderer();
		viewspanel.setLayout(new GridLayout(lines,coluns));
   		for(int i=0;i<NVIEWS;i++)
   		{
   			cams[i].canvas.truePostRender();
   			cams[i].canvas.startRenderer();
   			
   			cams[i].canvas.validate();
   			viewspanel.doLayout();
			views[i].doLayout();
   			viewspanel.add(views[i]);
   			cams[i].canvas.addNotify();
   			//cams[i].canvas.caminfo=false;
   		
   		}
   		viewspanel.doLayout();
   		Dimension d2=new Dimension();
   		//d= viewspanel.getSize();
   		d2.setSize(1,1);
   		for(int i=0;i<NVIEWS;i++)
   		{
   			views[i].doLayout();
   			
   		
   			//cams[i].canvas.paint(cams[i].canvas.g2);
			
   			//cams[i].canvas.doLayout();
   			//cams[i].canvas.repaint();
   			
   		}
   		//cams[panel_max].canvas.caminfo=auxc;   //info cam 
		panel_max=-1;
		//viewspanel.setSize(d2);
		//d= viewspanel.getSize();
		//d.setSize(d.width,d.height);
		//Dimension d2=new Dimension();
		//d2.setSize(1,1);
		//viewspanel.setSize(d2);
		//d.setSize(d.height,d.width);
		//viewspanel.setSize(d);
		//cams[0].setPhi(cams[0].phi);
		
		return;
	}

	if ("move".equals(e.getActionCommand())) {
		if (viewing==1) setViewMode(Renderer3D.NONE);
		else
		{
			setViewMode(Renderer3D.TRANSLATION);
			//viewing=1;
		}
		sendChangeEvent();	
		
		return;
	}
	if ("zoom".equals(e.getActionCommand())) {
		if (viewing==2) setViewMode(Renderer3D.NONE);
		else
		{
			setViewMode(Renderer3D.ZOOM);
			//viewing=2;
		}		
		sendChangeEvent();
		
		return;
	}
	if ("rotate".equals(e.getActionCommand())) {
		if (viewing==3) setViewMode(Renderer3D.NONE);
		else
		{
			setViewMode(Renderer3D.ROTATION);
			//viewing=3;
		}
		sendChangeEvent();
		
		return;
	}
	if ("resetmenu".equals(e.getActionCommand())) {
		
		return;
	}
	if ("resettop".equals(e.getActionCommand())) {
		cams[panel_op].resetTop();
		
		return;
	}
	if ("resetright".equals(e.getActionCommand())) {
		cams[panel_op].resetRight();
		
		return;
	}
	if ("resetback".equals(e.getActionCommand())) {
		cams[panel_op].resetBack();
		
		return;
	}
	if ("resetuser".equals(e.getActionCommand())) {
		cams[panel_op].resetUser();
		
		return;
	}
	if ("resetview".equals(e.getActionCommand())) {
		cams[panel_op].setType(cams[panel_op].type);
		
		return;
	}
	
	
	
	if ("grid".equals(e.getActionCommand())) {
		if(grid){
			contentsTransGr.removeChild(gridobj.getFullObj3D());
			grid=false;
		}
		else
		{
			gridobj.setPos(gcenter);
			gridobj.setParent3D(contentsTransGr);	
			grid=true;
		}
		
		return;
	}
	if ("menugrid".equals(e.getActionCommand())) {
		//Grid3D grid3Ddialog=new Grid3D();
		
		Grid3D.showGridDialog(this);
			
	
		return;
	}	
	if ("infocamera".equals(e.getActionCommand())) {
		if(cams[panel_op].canvas.caminfo){
			
			cams[panel_op].canvas.caminfo=false;
		}
		else
		{	
			cams[panel_op].canvas.caminfo=true;
		}
		
		return;
	}
	if ("infoaxis".equals(e.getActionCommand())) {
		if(cams[panel_op].canvas.axisinfo){
			
			cams[panel_op].canvas.axisinfo=false;
		}
		else
		{	
			cams[panel_op].canvas.axisinfo=true;
		}
		
		return;
	}
	if ("infoobj".equals(e.getActionCommand())) {
		if(cams[panel_op].canvas.objinfo){
			
			cams[panel_op].canvas.objinfo=false;
		}
		else
		{	
			cams[panel_op].canvas.objinfo=true;
		}
		
		return;
	}

	if ("Lock".equals(e.getActionCommand().substring(0, 4))) {
		System.err.println("Chamou Lock");
		for (Enumeration<String> enuma = Vehicles.keys(); enuma.hasMoreElements();) {
			String vt = (String) enuma.nextElement();
			if(e.getActionCommand().endsWith(vt))
			{
				Obj3D v3D=(Obj3D)Vehicles.get(vt);
				if(cams[panel_op].lockobj==v3D)
				{
					v3D.removeCamera3D(cams[panel_op]);
					viewTransGr.addChild(cams[panel_op].getCamera3D());
					cams[panel_op].lockobj=null;
				}
				else
				{
					if(cams[panel_op].lockobj!=null)
						cams[panel_op].lockobj.removeCamera3D(cams[panel_op]);
					else
						viewTransGr.removeChild(cams[panel_op].getCamera3D());
					v3D.addCamera3D(cams[panel_op]);
					cams[panel_op].lockobj=v3D;
				}
			}
				
							
		}

		
		
		return;
	}


	
}

public void infoCam (boolean flag)
{
	for (int i = 0;i<NVIEWS;i++)
		cams[i].canvas.caminfo=true;
}

public void infoAxis (boolean flag)
{
	for (int i = 0;i<NVIEWS;i++)
		cams[i].canvas.axisinfo=true;
}


public void grid(boolean g,boolean i)
{
	gtext=i;
	gUN=true;
	menuOKgrid();
	if(grid){
		contentsTransGr.removeChild(gridobj.getFullObj3D());
		grid=false;
	}
	else
	{
		gridobj.setPos(gcenter);
		gridobj.setParent3D(contentsTransGr);	
		grid=true;
	}
}


/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
 */

String agentToLock=null;
public void mouseClicked(MouseEvent e) {
	for(short i=0;i<NVIEWS;i++)
	{
		cams[i].canvas.selected=false;
		//cams[i].canvas.repaint();
		//cams[i].canvas.renderField(Canvas3D.FIELD_ALL);
		//cams[i].setPhi(cams[i].phi);
		if (e.getSource() == cams[i].canvas) {
		
			panel_op=i;
			//System.out.println(panel_op);
			//cams[i].canvas.renderField(MyCanvas3D.FIELD_ALL);
			//cams[panel_op].canvas.repaint();
			
			cams[panel_op].canvas.selected=true;
			cams[panel_op].setPhi(cams[i].phi);
			
		}
	}
	
	if (e.getButton() == MouseEvent.BUTTON1) 
	{
		if (viewing == Renderer3D.RULER)
		{
			if (rule==1)  // arrastou e clicou
			{
				rule=0;
				cams[panel_op].canvas.reguainfo=false;
			}
			else//(rule==0)   //clica
			{
				rule=1;
				cams[panel_op].canvas.reguainfo=true;
				cams[panel_op].canvas.p1.x=e.getX();
				cams[panel_op].canvas.p1.y=e.getY();
				cams[panel_op].canvas.p2.x=e.getX();
				cams[panel_op].canvas.p2.y=e.getY();
			}
			
		}
	}
	
		if (e.getButton() == MouseEvent.BUTTON3) {
			
				JPopupMenu popup = new JPopupMenu();
				popup.setLightWeightPopupEnabled(false);
				JPopupMenu.setDefaultLightWeightPopupEnabled(false);

				//popup.set
				JMenuItem item;
				if (NVIEWS!=1)   // s� uma vista est� sempre max...
				{
					item = new JMenuItem("Maximize");
					item.setActionCommand("maximize");
					item.addActionListener(this);
					if(panel_max!=-1) item.setEnabled(false);
					popup.add(item);

					item = new JMenuItem("Restore");
					item.setActionCommand("restore");
					if(panel_max==-1) item.setEnabled(false);
					item.addActionListener(this);
					popup.add(item);
				}
				
				item = new JMenuItem("Reset View");
				item.setActionCommand("resetview");
				item.addActionListener(this);
				popup.add(item);
				
				item = new JMenu("Viewing");
				popup.add(item);
				JCheckBoxMenuItem chekm=new JCheckBoxMenuItem("Move");
				chekm.setActionCommand("move");
				chekm.addActionListener(this);
				if(viewing==1)
					chekm.setSelected(true);
				item.add(chekm);
				JCheckBoxMenuItem chekz=new JCheckBoxMenuItem("Zoom");
				chekz.setActionCommand("zoom");
				if(viewing==2)
					chekz.setSelected(true);
				chekz.addActionListener(this);
				item.add(chekz);
				
				JCheckBoxMenuItem chekr=new JCheckBoxMenuItem("Rotate");
				chekr.setActionCommand("rotate");
				if(viewing==3)
					chekr.setSelected(true);
				chekr.addActionListener(this);
				item.add(chekr);
				
				JMenu reset = new JMenu("Select View");
				popup.add(reset);
				JMenuItem resetitem = new JMenuItem("Top");
				resetitem.setActionCommand("resettop");
				resetitem.addActionListener(this);
				reset.add(resetitem);
				resetitem = new JMenuItem("Right");
				resetitem.setActionCommand("resetright");
				resetitem.addActionListener(this);
				reset.add(resetitem);
				resetitem = new JMenuItem("Back");
				resetitem.setActionCommand("resetback");
				resetitem.addActionListener(this);
				reset.add(resetitem);
				resetitem = new JMenuItem("User");
				resetitem.setActionCommand("resetuser");
				resetitem.addActionListener(this);
				reset.add(resetitem);
				resetitem = new JMenuItem("Custom View...");
				resetitem.setActionCommand("custommenu");
				resetitem.addActionListener(this);
				reset.add(resetitem);
				
				
				
				/*item = new JMenu("Editing...");
				popup.add(item);*/
				popup.add(reset);
				
			
				
				JMenu grid = new JMenu("Grid");
				JCheckBoxMenuItem gridonoff=new JCheckBoxMenuItem("grid");
				gridonoff.setActionCommand("grid");
				gridonoff.setSelected(this.grid);
				gridonoff.addActionListener(this);
				grid.add(gridonoff);
				JMenuItem menugrid = new JMenuItem("Menu Grid");
				menugrid.setActionCommand("menugrid");
				menugrid.addActionListener(this);
				grid.add(menugrid);
				
				popup.add(grid);
				
				
				

				item = new JMenu("Infos");
				popup.add(item);
				chekm=new JCheckBoxMenuItem("Camera");
				chekm.setActionCommand("infocamera");
				chekm.addActionListener(this);
				if(cams[panel_op].canvas.caminfo)
					chekm.setSelected(true);
				item.add(chekm);
				chekz=new JCheckBoxMenuItem("Axis");
				chekz.setActionCommand("infoaxis");
				if(cams[panel_op].canvas.axisinfo)
					chekz.setSelected(true);
				chekz.addActionListener(this);
				//chekz.setEnabled(false);
				item.add(chekz);
				

				
				item = new JMenu("Lock View");
				popup.add(item);
				for (Enumeration<String> enuma = Vehicles.keys(); enuma.hasMoreElements();) {
					String vt = (String) enuma.nextElement();
					Obj3D v3D=(Obj3D)Vehicles.get(vt);
					chekm=new JCheckBoxMenuItem("Lock "+vt);
					chekm.setActionCommand("Lock"+vt);
					chekm.addActionListener(this);
					if(cams[panel_op].lockobj==v3D)
						chekm.setSelected(true);
					item.add(chekm);
					
					//v3D.setPos(location.getOffsetFrom());	
									
				}
				

				/*chekz=new JCheckBoxMenuItem("Objects");
				chekz.setActionCommand("infoobj");
				if(cams[panel_op].canvas.objinfo)
					chekz.setSelected(true);
				chekz.addActionListener(this);
				//chekz.setEnabled(false);
				item.add(chekz);
				*/
				

			
				
				
				
				popup.show(views[panel_op], e.getX(), e.getY());

			
			}
		}
	

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
 */
public void mouseEntered(MouseEvent e) {
	// TODO Auto-generated method stub

	//System.out.println("arastou");

}
/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
 */
public void mouseExited(MouseEvent arg0) {
	// TODO Auto-generated method stub

}

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
 */
public void mousePressed(MouseEvent e) {
	// TODO Auto-generated method stub
	if (e.getButton() == MouseEvent.BUTTON1) {
		//System.out.println("press1");
		mouse1=true;
		mousex=e.getX();mousey=e.getY();
	}
	if (e.getButton() == MouseEvent.BUTTON3) {
		//System.out.println("press1");
		mouse3=true;
		mousex=e.getX();mousey=e.getY();
	}
}

/* (non-Javadoc)
 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
 */
public void mouseReleased(MouseEvent e) {
	//// TODO Auto-generated method stub
	//System.out.println("rel");
	if (e.getButton() == MouseEvent.BUTTON1) {
		//System.out.println("rel1");
		mouse1=false;
	}
	if (e.getButton() == MouseEvent.BUTTON3) {
		//System.out.println("rel1");
		mouse3=false;
	}
}

/* (non-Javadoc)
 * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
 */
	/*private void move**/ 
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub
		//if (e.isAltDown()) {
		if (mouse1) {
			if (viewing == 3)
				for (short i = 0; i < NVIEWS; i++)
					if (e.getSource() == cams[i].canvas) {
						int mx = e.getX(), my = e.getY();

						if (e.isShiftDown()||cams[i].projection==View.PERSPECTIVE_PROJECTION) {
							cams[i].setPsi(cams[i].psi + ((mousex - mx) / 50.));
							cams[i].setTheta(cams[i].theta
									+ ((mousey - my) / 50.));
						} else {
							cams[i].setPhi(cams[i].phi + ((mousex - mx) / 50.));
						}
						mousex = mx;
						mousey = my;
					}
			if (viewing == 1) //
				for (short i = 0; i < NVIEWS; i++)
					if (e.getSource() == cams[i].canvas) {
						int auxx=views[i].getWidth();
						int auxy=views[i].getHeight();
						int mx = e.getX(), my = e.getY();
						int difx=mousex - mx;
						int dify=mousey - my;
						switch (cams[i].type) { 
						case Camera3D.TOP:{ 
							if (!e.isShiftDown()) {
								Vector3d vec = cams[i].pivot;
								Vector3d vaux=new Vector3d();
								vaux.y =1;
								vaux.x =1;
								
								vaux.x = difx / ((cams[i].scale/2))/(auxx);
								vaux.y = -dify / ((cams[i].scale/1.51))/(auxy);
								
								Vector3d vaux2=new Vector3d();
								vaux2.x =(vaux.x*Math.cos(-cams[i].phi))-(vaux.y*Math.sin(-cams[i].phi));
								vaux2.y =(vaux.x*Math.sin(-cams[i].phi))+(vaux.y*Math.cos(-cams[i].phi));
								
								//System.out.println(cams[i].phi);
								vec.y += vaux2.y;
								vec.x += vaux2.x;
								//vec.y += difx / ((cams[i].scale/2))/(auxx);
								//vec.x += -dify / ((cams[i].scale/1.51))/(auxy);								
								cams[i].setPivot(vec);

							} else {
								Vector3d vec = cams[i].pivot;
								vec.z += dify / (cams[i].scale*150.);
								cams[i].setPivot(vec);
							}
							break;
						}
						case Camera3D.BACK:{
							if (!e.isShiftDown()) {
								
								Vector3d vec = cams[i].pivot;
								
								Vector3d vaux=new Vector3d();
								vaux.x =1;
								vaux.z =1;
								
								vaux.x = difx / ((cams[i].scale/2))/(auxx);
								vaux.z = -dify / ((cams[i].scale/1.51))/(auxy);
								
								Vector3d vaux2=new Vector3d();
								vaux2.x =(vaux.x*Math.cos(-cams[i].phi))-(vaux.z*Math.sin(-cams[i].phi));
								vaux2.z =(vaux.x*Math.sin(-cams[i].phi))+(vaux.z*Math.cos(-cams[i].phi));
								
								vec.x += vaux2.x;
								vec.z += vaux2.z;
								//vec.x += difx / ((cams[i].scale/2))/(auxx);
								//vec.z += dify / ((cams[i].scale/1.51))/(auxy);

								cams[i].setPivot(vec);

							} 
							else 
							{
								Vector3d vec = cams[i].pivot;
								vec.y += dify / (cams[i].scale*150.);
								cams[i].setPivot(vec);
							}
							break;
						}
						case Camera3D.RIGHT:{
							if (!e.isShiftDown()) {
								Vector3d vec = cams[i].pivot;
								
								Vector3d vaux=new Vector3d();
								vaux.y =1;
								vaux.z =1;
								
								vaux.y = difx / ((cams[i].scale/2))/(auxx);
								vaux.z = -dify / ((cams[i].scale/1.51))/(auxy);
								
								Vector3d vaux2=new Vector3d();
								vaux2.y =(vaux.y*Math.cos(-cams[i].phi))-(vaux.z*Math.sin(-cams[i].phi));
								vaux2.z =(vaux.y*Math.sin(-cams[i].phi))+(vaux.z*Math.cos(-cams[i].phi));
								
								
								vec.y += vaux2.y;
								vec.z += vaux2.z;
								//vec.y += difx / ((cams[i].scale/2))/(auxx);
								//vec.z += dify / ((cams[i].scale/1.51))/(auxy);
								
								cams[i].setPivot(vec);

							} else {
								Vector3d vec = cams[i].pivot;
								vec.x += dify / (cams[i].scale*150.);
								cams[i].setPivot(vec);
							}
							break;
						}
						case Camera3D.USER:{ 
							if (!e.isShiftDown()) {
								Vector3d vec = cams[i].pivot;
								Vector3d vaux=new Vector3d();
								vaux.y =1;
								vaux.x =1;
								
								vaux.y = difx / (150/(cams[i].rho));
								vaux.x = -dify / (150/(cams[i].rho));
								
								Vector3d vaux2=new Vector3d();
								vaux2.x =(vaux.y*Math.cos(cams[i].psi))-(vaux.x*Math.sin(cams[i].psi));
								vaux2.y =(vaux.y*Math.sin(cams[i].psi))+(vaux.x*Math.cos(cams[i].psi));
								
								//System.out.println(cams[i].phi);
								vec.y += vaux2.y;
								vec.x += vaux2.x;
								//vec.y += difx / (150/(cams[i].rho));
								//vec.x += -dify / (150/(cams[i].rho));

								cams[i].setPivot(vec);

							} else {
								Vector3d vec = cams[i].pivot;
								vec.z -= dify / (150/(cams[i].rho));
								cams[i].setPivot(vec);
							}
							break;
						}
						
						default:{
							if (!e.isShiftDown()) {
								Vector3d vec = cams[i].pivot;
								vec.x += difx / (cams[i].scale*150.);
								vec.y += -dify / (cams[i].scale*150.);

								cams[i].setPivot(vec);

							} else {
								Vector3d vec = cams[i].pivot;
								vec.z += dify / (cams[i].scale*150.);
								cams[i].setPivot(vec);
							}
							
					    	
							}
						
						}
						mousex = mx;
						mousey = my;
					}
				
			if (viewing == 2)
				for (short i = 0; i < NVIEWS; i++)
					if (e.getSource() == cams[i].canvas) {
						int mx = e.getX(), my = e.getY();

						if (cams[i].projection == View.PERSPECTIVE_PROJECTION) {
							if (!e.isShiftDown())
								cams[i].setRho(cams[i].rho
										+ ((my-mousey) / 30.));
							else
								cams[i].setScale(cams[i].scale
										+ ((my-mousey) / 150.));
						} else {
							if (!e.isShiftDown())
								cams[i].setScale(cams[i].scale
										+ ((mousey-my) / 150.));
							else
								cams[i].setRho(cams[i].rho
										+ ((mousey-my) / 30.));

						}
						mousex = mx;
						mousey = my;
					}
			//System.out.println("drag");
		}
		
		if (mouse3) {
			if (viewing == 3)
				for (short i = 0; i < NVIEWS; i++)
					if (e.getSource() == cams[i].canvas) {
						int mx = e.getX(), my = e.getY();
						cams[i].setPhi(cams[i].phi + ((mousex - mx) / 50.));
					
						mousex = mx;
						mousey = my;
					}
		
					if (viewing == 1) //
						for (short i = 0; i < NVIEWS; i++)
							if (e.getSource() == cams[i].canvas) {
								int mx = e.getX(), my = e.getY();
								int difx=mousex - mx;
								int dify=mousey - my;
								switch (cams[i].type) { 
								case Camera3D.TOP:{ 

										Vector3d vec = cams[i].pivot;
										vec.z += dify / (cams[i].scale*150.);
										cams[i].setPivot(vec);

									break;
								}
								case Camera3D.RIGHT:{
										Vector3d vec = cams[i].pivot;
										vec.y += dify / (cams[i].scale*150.);
										cams[i].setPivot(vec);
									break;
								}
								case Camera3D.BACK:{
										Vector3d vec = cams[i].pivot;
										vec.x += dify / (cams[i].scale*150.);
										cams[i].setPivot(vec);

									break;
								}
								case Camera3D.USER:{ 
										Vector3d vec = cams[i].pivot;
										vec.z += dify / (150/(cams[i].rho)); 
										cams[i].setPivot(vec);

									break;
								}
								
								default:{
										Vector3d vec = cams[i].pivot;
										vec.z += dify / (cams[i].scale*150.);
										cams[i].setPivot(vec);

									
							    	
									}
								
								}
								mousex = mx;
								mousey = my;
							}
					
					
					
					
			if (viewing == 2)
				for (short i = 0; i < NVIEWS; i++)
					if (e.getSource() == cams[i].canvas) {
						int mx = e.getX(), my = e.getY();

						if (cams[i].projection == View.PERSPECTIVE_PROJECTION) {
					
								cams[i].setScale(cams[i].scale
										+ ((my-mousey) / 150.));
						} else {
								cams[i].setRho(cams[i].rho
										+ ((mousey-my) / 30.));

						}
						mousex = mx;
						mousey = my;
					}
			//System.out.println("drag");
		}
		//}
	}

/* (non-Javadoc)
 * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
 */
public void mouseMoved(MouseEvent e) {
	// TODO Auto-generated method stub
	//System.out.println("move");
	
	if (viewing == Renderer3D.RULER && e.getSource() == cams[panel_op].canvas)
		if (rule==1)  // arrastou e clicou
		{
		
			cams[panel_op].canvas.p2.x=e.getX();
			cams[panel_op].canvas.p2.y=e.getY();
			cams[panel_op].setPhi(cams[panel_op].phi);
		}
}


public void componentResized(ComponentEvent e) {
	// TODO Auto-generated method stub
	//for(int i=0;i<NVIEWS;i++)
	//	cams[i].canvas.repaint();		
	
}

/*private Shape3D pick(Canvas3D canvas, BranchGroup rootBranchGroup, int x, int y,
		 Point3d pickedPoint)
		 {
		     PickObject po = new PickObject(canvas, rootBranchGroup);
		     SceneGraphPath sgp = po.pickClosest(x, y, PickObject.USE_GEOMETRY);
		     if(sgp!=null) {
		        PickRay ray = (PickRay)po.generatePickRay(x,y);
		         double distance[] = new double[1];
		         Vector3d rayvect = new Vector3d();
		         for( int i=sgp.nodeCount()-1 ; i>=0 ; i-- ) {
		             if(sgp.getNode(i) instanceof Shape3D) {
		                 Shape3D pickedShape = (Shape3D)sgp.getNode(i);
		                 if(pickedShape.intersect(sgp, ray, distance)) {
		                     ray.get(pickedPoint, rayvect);
		                     rayvect.scale(distance[0]);
		                     pickedPoint.add(rayvect);
		                     return pickedShape;
		                 }
		             }
		         }
		     }
		     return null;
		 }
*/ 
	 /* (non-Javadoc)
	 * @see pt.up.fe.dceg.neptus.renderer2d.Renderer#focusLocation(pt.up.fe.dceg.neptus.types.coord.AbstractLocationPoint)
	 */
	public void focusLocation(double d[]) {
		// TODO Auto-generated method stub
		//location.getOffsetFrom();

		double newpos2[]=seaobj.pos;
					newpos2[0]+=d[0];
					newpos2[1]+=d[1];
					newpos2[2]+=d[2];
					seaobj.setPos(newpos2);
		
		newpos2=gridobj.pos;
					newpos2[0]+=d[0];
					newpos2[1]+=d[1];
					newpos2[2]+=d[2];
					gridobj.setPos(newpos2);
		

			/*		
		for (Enumeration enuma = objects.keys(); enuma.hasMoreElements();) {
					MapObject vt = (MapObject) enuma.nextElement();
					Obj3D v3D=(Obj3D)vehicles.get(vt);
					double newpos[]=v3D.pos;
					newpos[0]-=d[0];
					newpos[1]-=d[1];
					newpos[2]-=d[2];
					v3D.setPos(newpos);
					//v3D.setPos(location.getOffsetFrom());	
									
					}
		*/
			
	//TODO ver isto 
		/*Obj3D[] objarray=new Obj3D[0];
		Iterator it =  objects.values().iterator();
		while (it.hasNext())
		{
			Obj3D obj = (Obj3D) it.next();
			double newpos[]=obj.pos;
			newpos[0]+=d[0];
			newpos[1]+=d[1];
			newpos[2]+=d[2];
			obj.setPos(newpos);
		}*/
				//this.location.setLocation(location);
		/*
		Collection col=objects.values();
		if (!col.isEmpty())
			for (int i =0;i<objects.values().toArray().length;i++)
				objarray[i]= (Obj3D) objects.values().toArray()[i];
		else 
			System.out.println("erro");
		for(int i=0;i<objarray.length;i++)
		{
			double newpos[]=objarray[i].pos;
			newpos[0]+=d[0];
			newpos[1]+=d[1];
			newpos[2]+=d[2];
			objarray[i].setPos(newpos);
		}
		*/
	
	}
	
	/* (non-Javadoc)
	 * @see pt.up.fe.dceg.neptus.renderer2d.Renderer#focusObject(pt.up.fe.dceg.neptus.mme.objects.MapObject)
	 */

	/* (non-Javadoc)
	 * @see pt.up.fe.dceg.neptus.mp.MapChangeListener#mapChanged(pt.up.fe.dceg.neptus.mp.MapChangeEvent)
	 */
	
	

	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
	 */
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub

		for (short i = 0; i < NVIEWS; i++)
			if (e.getSource() == cams[i].canvas) {
				if (KeyEvent.VK_F1 == (e.getKeyCode())) {
					cams[i].resetTop();
				}
				if (KeyEvent.VK_F2 == (e.getKeyCode())) {
					cams[i].resetRight();
				}
				if (KeyEvent.VK_F3 == (e.getKeyCode())) {
					cams[i].resetBack();
				}
				if (KeyEvent.VK_F4 == (e.getKeyCode())) {
					cams[i].resetUser();
				}
				if(e.isControlDown()){
					if (KeyEvent.VK_R == (e.getKeyCode())) {
						viewing=Renderer3D.ROTATION;
						sendChangeEvent();
					}
					if (KeyEvent.VK_M == (e.getKeyCode())) {
						viewing=Renderer3D.TRANSLATION;
						sendChangeEvent();
					}
					if (KeyEvent.VK_V == (e.getKeyCode())) {
						viewing=Renderer3D.TRANSLATION;
						sendChangeEvent();
					}
					if (KeyEvent.VK_Z == (e.getKeyCode())) {
						viewing=Renderer3D.ZOOM;
						sendChangeEvent();
					}
					if (KeyEvent.VK_T == (e.getKeyCode())) {
						viewing=Renderer3D.TRANSLATION;
						sendChangeEvent();
					}
				}
				if(e.isAltDown()){
					if (KeyEvent.VK_C == (e.getKeyCode())) {
						if(cams[panel_op].canvas.caminfo){
							
							cams[panel_op].canvas.caminfo=false;
						}
						else
						{	
							cams[panel_op].canvas.caminfo=true;
						}
					}
					if (KeyEvent.VK_M == (e.getKeyCode())) {
						viewing=1;
						sendChangeEvent();
					}
					if (KeyEvent.VK_V == (e.getKeyCode())) {
						viewing=1;
						sendChangeEvent();
					}
					if (KeyEvent.VK_Z == (e.getKeyCode())) {
						viewing=2;
						sendChangeEvent();	
					}
				}
			}
				
	}

	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	public void setViewMode(int mode) {
		//final int TRANSLATION = 1, ZOOM = 2, ROTATION = 3, NONE = -1;
		//TODO Do this...
		viewing=(short)mode;
		if (rotateCursor == null) {
			loadCursors();
		}
		switch (mode) {
		case (Renderer3D.ROTATION):
			for(int i=0;i<NVIEWS;i++)
				views[i].setCursor(rotateCursor);
			break;
		case (Renderer3D.TRANSLATION):
			for(int i=0;i<NVIEWS;i++)
				views[i].setCursor(translateCursor);
			break;
		case (Renderer3D.ZOOM):
			for(int i=0;i<NVIEWS;i++)
				views[i].setCursor(zoomCursor);
			break;
		case (Renderer3D.RULER):
			for(int i=0;i<NVIEWS;i++)
				views[i].setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
			break;
		default:{
			for(int i=0;i<NVIEWS;i++)
				views[i].setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			}
		}
 		
	}
	

	

	private Vector changeListeners = new Vector();
	
	public void addChangeListener(ChangeListener cl) {
		changeListeners.add(cl);
	}
	
	public void removeChangeListener(ChangeListener cl) {
		changeListeners.remove(cl);
	}
	
	public int getCurrentMode() {
		return (int) viewing;
	}
	
	private void sendChangeEvent() {
		for (int i = 0; i < changeListeners.size(); i++) {
			ChangeEvent ce = new ChangeEvent(this);
			((ChangeListener) changeListeners.get(i)).stateChanged(ce);
		}
	}

	/* (non-Javadoc)
	 * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
	 */
	public void mouseWheelMoved(MouseWheelEvent e) {
		// TODO Auto-generated method stub
		for (short i = 0; i < NVIEWS; i++)
			if (e.getSource() == cams[i].canvas) {
				int mw = e.getWheelRotation();

				if (cams[i].projection == View.PERSPECTIVE_PROJECTION) {
					if (!e.isShiftDown())
						cams[i].setRho(cams[i].rho
								+ ((mw*(cams[i].rho/1.1)) / 30.));
					else
					{
						cams[i].setScale(cams[i].scale
								+ ((mw*10) / 150.));
						System.out.println(cams[i].scale
								+ ((mw*10) / 150.));
					}
				} else {
					if (!e.isShiftDown())
						cams[i].setScale(cams[i].scale
								+ ((-mw*10) * (cams[i].scale/100.)));
					else
						cams[i].setRho(cams[i].rho
								+ ((-mw*(cams[i].rho/1.1)) / 30.));

				}		
			}
		
		
	}
	
	
	public Appearance createAppearance(){
		Appearance app = new Appearance();
		app.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
		Material mat = new Material();
		mat.setCapability(Material.ALLOW_COMPONENT_WRITE);
		mat.setDiffuseColor(new Color3f(1.0f,0.0f,0.0f));
		mat.setSpecularColor(new Color3f(1.0f,0.0f,0.0f));
		app.setMaterial(mat);
		
		TransparencyAttributes trans=new TransparencyAttributes();
	   	trans.setTransparency(0.5f);
	   	trans.setTransparencyMode(TransparencyAttributes.BLEND_ONE);
	   	app.setTransparencyAttributes(trans);
		
		return app;
	}

	   //public Hashtable<VehicleState, Obj3D> Vehicles=new Hashtable<VehicleState, Obj3D>();
	public void newState(VehicleState vs)
	{
		Sphere s=new Sphere(30,createAppearance());
		Obj3D dest=null;
		
		if(vs!=null)
		{
			Point3d p=vs.getDestination();
			if(p!=null)
			{
				
					dest=destination.get(vs.getId());
					if(dest ==null)
					{
					dest=new Obj3D();
					TransformGroup tg=new TransformGroup();
					tg.addChild(s);
					dest.setModel3D(tg);
					dest.setPos(p);
					addObj3D(dest);
					destination.put(vs.getId(), dest);
					}
					else
					{
						dest.setPos(p);
					}
			}
			else
			{
				dest=destination.get(vs.getId());
				if(dest !=null)
				{
					removeObj3D(dest);
				}
			}
		}
		
		
		Obj3D found=Vehicles.get(vs.getId());
		if(found!=null)
		{
			found.setPos(vs.getPoint());
			//System.out.println("point"+vs.getPoint());
			found.setYaw(vs.getYaw());
			
			
			found.destination=vs.getDestination();
			/*
			if (vs.getDestination()==null)
			{
				found.loiter=true;
			}
			else
				found.loiter=false;
			*/
			//System.out.println("Moved the object to "+vs.getPoint());
		}
		else
		{
			Obj3D vhe=new Obj3D();
			
			/*File file=null;
			System.out.println(vs.getModel());
			if (getClass().getClassLoader().getResource(vs.getModel()) != null) 
				file=new File(getClass().getClassLoader().getResource(vs.getModel()).getFile());			
			else
				file=new File(getClass().getClassLoader().getResource("models/apv.3ds").getFile());
			
			Inspector3DS loader  = new Inspector3DS(file.getAbsolutePath());
			loader.parseIt(); // process the file
			TransformGroup theModel1  = loader.getModel(); // get the resulting 3D
			*/
			
			/*TransformGroup theModel1  = new TransformGroup();
			if(vs.getModel().equals("apv"))
				theModel1=(TransformGroup) APVModel.cloneTree();
			if(vs.getModel().equals("lusitania"))
				theModel1=(TransformGroup) APVModel.cloneTree();
			if(vs.getModel().equals(""))
				theModel1=(TransformGroup) APVModel.cloneTree();
			*/
			
			TransformGroup theModel1  = null;
			for (Enumeration<String> enuma=models.keys();enuma.hasMoreElements();)
			{
				String id=enuma.nextElement();
				if(id.equals(vs.getId()))
				{
					theModel1=(TransformGroup) models.get(vs.getId()).cloneTree();
				}
			}
			
			if(theModel1==null)
			{
				theModel1=(TransformGroup) models.get("apv").cloneTree();
				
			}
			/*System.err.println("##############################################\n" +
					"##############################################\n" +
					"##############################################\n" +
					"##############################################\n" +
					"##############################################\n" +
					"##############################################\n" +
					"##############################################\n" +
					"##############################################\n" +
					theModel1);
			//theModel1.addChild(s);
			*/
			
			/*TransformGroup tg=new TransformGroup();
			tg.addChild(new Sphere(2));
			Transform3D r=new Transform3D();
			r.set(new Vector3d(3, 0, 0));
			tg.setTransform(r);
			vhe.addTG(tg);*/
			vhe.setModel3D(theModel1);
			
			vhe.setPos(vs.getPoint());
			vhe.setYaw(vs.getYaw());
			
			Vehicles.put(vs.getId(),vhe);
			addObj3D(vhe);
		  	
		}
		
		
	}

}
